package cn.gogpay.dcb.api.service;

import cn.gogpay.dcb.api.dao.PullQrCodeRecordRepository;
import cn.gogpay.dcb.api.dao.UserBusCardRepository;
import cn.gogpay.dcb.api.dto.qrcode.ActivateCardDTO;
import cn.gogpay.dcb.api.dto.qrcode.GetBalanceDTO;
import cn.gogpay.dcb.api.dto.qrcode.PullQrCodeDTO;
import cn.gogpay.dcb.api.entity.PullQrCodeRecord;
import cn.gogpay.dcb.api.entity.UserBusCard;
import cn.gogpay.dcb.api.feign.ApiPlatformClient;
import cn.gogpay.dcb.api.feign.IcbcWalletClient;
import cn.gogpay.dcb.api.web.form.CountForm;
import cn.gogpay.dcb.common.dto.ResultCode;
import cn.gogpay.dcb.common.dto.ResultDTO;
import cn.gogpay.dcb.common.exception.ServiceException;
import cn.gogpay.dcb.common.util.DateUtils;
import cn.gogpay.dcb.h5base.dto.UserDTO;
import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Example;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * @author jiaoming@gogpay.cn
 * @date 2019/12/2 22:04
 */
@Service
public class UserBusCardService {
    private static final Logger logger = LoggerFactory.getLogger(UserBusCardService.class);

    @Autowired
    private UserBusCardRepository userBusCardRepository;

    @Autowired
    private ApiPlatformClient apiPlatformClient;

    @Autowired
    private PullQrCodeRecordRepository pullQrCodeRecordRepository;

    @Autowired
    private OutService outService;

    @Autowired
    private IcbcWalletClient icbcWalletClient;

    @Autowired
    private UserBusCardService userBusCardService;

    @Value("${free.test:true}")
    private Boolean freeTest;

    @Value("${free.test.phone}")
    private String freeTestPhone;

    /**
     * 拉取乘车二维码
     *
     * @param userId    用户id
     * @param userPhone 用户手机号
     * @return
     */
    public ResultDTO pullQrCode(String userId, String userPhone) {

        String cardNo = this.findByUserId(userId).getCardNo();

        PullQrCodeDTO pullQrCodeDTO = new PullQrCodeDTO();
        pullQrCodeDTO.setCardNo(cardNo);
        pullQrCodeDTO.setUserId(userId);
        pullQrCodeDTO.setUserPhone(userPhone);

        ResultDTO resultDTO = this.apiPlatformClient.pullQrCode(pullQrCodeDTO);

        if (!resultDTO.isSuccess()) {
            return resultDTO;
        }
        JSONObject data = (JSONObject) resultDTO.getData();
        Integer code = data.getInteger("code");
        String msg = data.getString("msg");

        if (code == 200) {

            String qrInfo = data.getJSONObject("result").getString("qrInfo");
            String saveData = qrInfo;
            qrInfo = qrInfo.replaceAll("\r\n", "");

            /**
             * 增加base64图片头
             */
            if (!qrInfo.contains("data:image/png;base64,")) {
                qrInfo = "data:image/png;base64," + qrInfo;
            }

            JSONObject jsonObject = new JSONObject();
            jsonObject.put("qrInfo", qrInfo);

            // 存储此次拉码数据
            PullQrCodeRecord record = new PullQrCodeRecord();
            record.setUserId(userId);
            record.setCardNo(cardNo);
            record.setPhone(userPhone);
            record.setPullDate(DateUtils.getNow());
            record.setQrCode(saveData);
            pullQrCodeRecordRepository.save(record);

            return new ResultDTO(ResultCode.tradeSuccess().code(), "请求成功", jsonObject);
        }
        /**
         * 余额不足
         */
        if (code == -1 && msg.equals("该账号余额不足,请充值")) {
            return new ResultDTO(10005, msg);
        }
        return new ResultDTO(code, msg);
    }

    public UserBusCard findByUserId(String userId) {
        UserBusCard userBusCard = new UserBusCard();
        userBusCard.setUseId(userId);
        Example<? extends UserBusCard> example = Example.of(userBusCard);
        return this.userBusCardRepository.findOne(example).orElse(null);
    }

    /**
     * 是否已经开卡
     *
     * @param userId
     * @return
     */
    public boolean hasOpenBusCard(String userId) {
        UserBusCard userBusCard = new UserBusCard();
        userBusCard.setUseId(userId);
        Example<? extends UserBusCard> example = Example.of(userBusCard);
        return this.userBusCardRepository.exists(example);
    }

    /**
     * 余额查询
     *
     * @param phoneNo
     * @return
     */
    public ResultDTO getBalance(String phoneNo) {

        GetBalanceDTO getBalanceDTO = new GetBalanceDTO();
        getBalanceDTO.setUserPhone(phoneNo);

        ResultDTO resultDTO = this.apiPlatformClient.getBalance(getBalanceDTO);

        if (!resultDTO.isSuccess()) {
            return resultDTO;
        }
        JSONObject data = (JSONObject) resultDTO.getData();
        Integer code = data.getInteger("code");
        String msg = data.getString("msg");

        if (code == 200) {
            String balance = data.getJSONObject("result").getString("money");
            String cardNo = data.getJSONObject("result").getString("cardNo");

            JSONObject jsonObject = new JSONObject();
            // balance
            jsonObject.put("balance", balance);
            jsonObject.put("cardNo", cardNo);

            return new ResultDTO(ResultCode.tradeSuccess().code(), "请求成功", jsonObject);
        }
        return new ResultDTO(code, msg);
    }

    /**
     * 开卡
     *
     * @param userId
     * @param phoneNo
     * @return
     */
    public ResultDTO activeCard(String userId, String phoneNo) {
        /**
         * 1、根据数据库记录判断是否已经开卡
         */
        UserBusCard userCard = this.findByUserId(userId);
        if (userCard != null) {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("cardNo", userCard.getCardNo());
            return new ResultDTO(ResultCode.tradeSuccess().code(), "请求成功", jsonObject);
        }

        /**
         * 2、调用公交公司接口进行开卡
         */
        ActivateCardDTO activateCardDTO = new ActivateCardDTO();
        activateCardDTO.setUserId(userId);
        activateCardDTO.setUserPhone(phoneNo);

        ResultDTO resultDTO = this.apiPlatformClient.activateCard(activateCardDTO);
        if (!resultDTO.isSuccess()) {
            return resultDTO;
        }

        JSONObject data = (JSONObject) resultDTO.getData();
        Integer code = data.getInteger("code");
        String msg = data.getString("msg");

        if (code == 200) {
            String cardNo = data.getJSONObject("result").getString("cardNo");
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("cardNo", cardNo);
            /**
             * 将用户的卡开信息存储到数据库中
             */
            UserBusCard userBusCard = new UserBusCard();
            userBusCard.setUseId(userId);
            userBusCard.setCardNo(cardNo);
            this.userBusCardRepository.saveAndFlush(userBusCard);

            return new ResultDTO(ResultCode.tradeSuccess().code(), "请求成功", jsonObject);
        }
        return new ResultDTO(code, msg);
    }

    /**
     * 获得result 中的数据
     *
     * @param resultDTO
     * @return
     */
    private JSONObject getData(ResultDTO resultDTO) {
        Integer status = resultDTO.getStatus();
        if (ResultCode.SUCCESS_CODE != status) {
            throw new ServiceException(resultDTO.getMsg());
        }
        JSONObject getObj = JSONObject.parseObject(JSONObject.toJSONString(resultDTO));
        return getObj;
    }

    /**
     * 是否开通且可用次数
     *
     * @param userDTO
     * @return
     */
    public Map<String, Object>
    isOpenAndCount(UserDTO userDTO) {
        ResultDTO openAccount = icbcWalletClient.isOpenAccount(userDTO.getUserId());
        JSONObject jsonObject = this.getData(openAccount);
        JSONObject data = jsonObject.getJSONObject("data");
        Boolean open = data.getBoolean("open");
        String jumpUrl = data.getString("url");
        Map<String, Object> map = new HashMap<>(6);
        map.put("url", jumpUrl);
        map.put("freeCount", 0);
        if (open) {
            Optional<List<UserBusCard>> desc = userBusCardRepository.findAllByUseIdOrderByCreatedDateDesc(userDTO.getUserId());
            if (desc.isPresent() && desc.get().size() > 0) {
                UserBusCard userBusCard = desc.get().get(0);
                String cardNo = userBusCard.getCardNo();
                CountForm countForm = new CountForm();
                countForm.setCardNo(cardNo);
                countForm.setPhone(userDTO.getPhoneNo());
                Integer integer = outService.useCount(countForm, userDTO.getUserId());
                Boolean carMaster = outService.isCarMaster(userDTO.getAuthName(), userDTO.getAuthCardNo());
                Integer count = 0;
                if (carMaster) {
                    Integer carMasterCount = outService.getCarMasterCount();
                    count = carMasterCount - integer;
                } else {
                    Integer normalCount = outService.getNormalCount();
                    count = normalCount - integer;
                }
                if (count < 0) {
                    count = 0;
                }
                map.put("freeCount", count);
            } else {
                open = false;
            }
        }
        //
        map.put("open", open);

        // 增加测试账号
        if (freeTest) {
            if (!freeTestPhone.contains(userDTO.getPhoneNo())) {
                map.put("freeCount", 0);
            }
        }


        // 增加余额不足1元不可免费
        /*try {
            ResultDTO balance = userBusCardService.getBalance(userDTO.getPhoneNo());
            JSONObject object = this.getData(balance);
            JSONObject balanceData = object.getJSONObject("data");
            String money = balanceData.getString("balance");
            double v = Double.parseDouble(money);
            if (v < 0.0) {
                map.put("url", jumpUrl);
                map.put("freeCount", 0);
                logger.warn("余额不足，不能免费，user:{}", userDTO);
            }
        } catch (Exception e) {
            logger.error("余额查询异常，{}", e);
        }*/

        return map;
    }
}
